home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PD Collection CD 1
/
PD Collection CD 1.iso
/
textual
/
pdftops
/
xpdf
/
c++
/
Gfx
< prev
next >
Wrap
Text File
|
1996-06-09
|
43KB
|
1,639 lines
//========================================================================
//
// Gfx.cc
//
// Copyright 1996 Derek B. Noonburg
//
//========================================================================
#ifdef __GNUC__
//#pragma implementation
#endif
#include <stdio.h>
#include <stddef.h>
#include <string.h>
// snb94r@ecs.soton.ac.uk added stdarg for the table construction
#include <stdarg.h>
#include "gmem.h"
#include "cover.h"
#include "Object.h"
#include "Array.h"
#include "Dict.h"
#include "Stream.h"
#include "Lexer.h"
#include "Parser.h"
#include "GfxFont.h"
#include "GfxState.h"
#include "OutputDev.h"
#include "PSOutput.h"
#include "Flags.h"
#include "Error.h"
#include "Gfx.h"
//------------------------------------------------------------------------
// Operator table
//------------------------------------------------------------------------
// snb94r@ecs.soton.ac.uk removed this static table, since cfront refuses
// to compile it, with a "initializer too long" error. The table is instead
// built dynamically with the new methods below.
#ifndef __riscos
Operator Gfx::opTab[] = {
{"\"", 3, {tchkNum, tchkNum, tchkString},
&Gfx::opMoveSetShowText, &Gfx::psMoveSetShowText},
{"'", 1, {tchkString},
&Gfx::opMoveShowText, &Gfx::psMoveShowText},
{"B", 0, {tchkNone},
&Gfx::opFillStroke, &Gfx::psFillStroke},
{"B*", 0, {tchkNone},
&Gfx::opEOFillStroke, &Gfx::psEOFillStroke},
{"BI", 0, {tchkNone},
&Gfx::opBeginImage, &Gfx::psBeginImage},
{"BT", 0, {tchkNone},
&Gfx::opBeginText, &Gfx::psBeginText},
{"Do", 1, {tchkName},
&Gfx::opXObject, &Gfx::psXObject},
{"EI", 0, {tchkNone},
&Gfx::opEndImage, &Gfx::psEndImage},
{"ET", 0, {tchkNone},
&Gfx::opEndText, &Gfx::psEndText},
{"F", 0, {tchkNone},
&Gfx::opFill, &Gfx::psFill},
{"G", 1, {tchkNum},
&Gfx::opSetStrokeGray, &Gfx::psSetStrokeGray},
{"ID", 0, {tchkNone},
&Gfx::opImageData, &Gfx::psImageData},
{"J", 1, {tchkInt},
&Gfx::opSetLineCap, &Gfx::psSetLineCap},
{"K", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
&Gfx::opSetStrokeCMYKColor, &Gfx::psSetStrokeCMYKColor},
{"M", 1, {tchkNum},
&Gfx::opSetMiterLimit, &Gfx::psSetMiterLimit},
{"Q", 0, {tchkNone},
&Gfx::opRestore, &Gfx::psRestore},
{"RG", 3, {tchkNum, tchkNum, tchkNum},
&Gfx::opSetStrokeRGBColor, &Gfx::psSetStrokeRGBColor},
{"S", 0, {tchkNone},
&Gfx::opStroke, &Gfx::psStroke},
{"T*", 0, {tchkNone},
&Gfx::opTextNextLine, &Gfx::psTextNextLine},
{"TD", 2, {tchkNum, tchkNum},
&Gfx::opTextMoveSet, &Gfx::psTextMoveSet},
{"TJ", 1, {tchkArray},
&Gfx::opShowSpaceText, &Gfx::psShowSpaceText},
{"TL", 1, {tchkNum},
&Gfx::opSetTextLeading, &Gfx::psSetTextLeading},
{"Tc", 1, {tchkNum},
&Gfx::opSetCharSpacing, &Gfx::psSetCharSpacing},
{"Td", 2, {tchkNum, tchkNum},
&Gfx::opTextMove, &Gfx::psTextMove},
{"Tf", 2, {tchkName, tchkNum},
&Gfx::opSetFont, &Gfx::psSetFont},
{"Tj", 1, {tchkString},
&Gfx::opShowText, &Gfx::psShowText},
{"Tm", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
tchkNum, tchkNum},
&Gfx::opSetTextMatrix, &Gfx::psSetTextMatrix},
{"Tr", 1, {tchkInt},
&Gfx::opSetTextRender, &Gfx::psSetTextRender},
{"Ts", 1, {tchkNum},
&Gfx::opSetTextRise, &Gfx::psSetTextRise},
{"Tw", 1, {tchkNum},
&Gfx::opSetWordSpacing, &Gfx::psSetWordSpacing},
{"Tz", 1, {tchkNum},
&Gfx::opSetHorizScaling, &Gfx::psSetHorizScaling},
{"W", 0, {tchkNone},
&Gfx::opClip, &Gfx::psClip},
{"W*", 0, {tchkNone},
&Gfx::opEOClip, &Gfx::psEOClip},
{"b", 0, {tchkNone},
&Gfx::opCloseFillStroke, &Gfx::psCloseFillStroke},
{"b*", 0, {tchkNone},
&Gfx::opCloseEOFillStroke, &Gfx::psCloseEOFillStroke},
{"c", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
tchkNum, tchkNum},
&Gfx::opCurveTo, &Gfx::psCurveTo},
{"cm", 6, {tchkNum, tchkNum, tchkNum, tchkNum,
tchkNum, tchkNum},
&Gfx::opConcat, &Gfx::psConcat},
{"d", 2, {tchkArray, tchkNum},
&Gfx::opSetDash, &Gfx::psSetDash},
{"d0", 2, {tchkNum, tchkNum},
&Gfx::opSetCharWidth, &Gfx::psSetCharWidth},
{"d1", 2, {tchkNum, tchkNum, tchkNum, tchkNum,
tchkNum, tchkNum},
&Gfx::opSetCacheDevice, &Gfx::psSetCacheDevice},
{"f", 0, {tchkNone},
&Gfx::opFill, &Gfx::psFill},
{"f*", 0, {tchkNone},
&Gfx::opEOFill, &Gfx::psEOFill},
{"g", 1, {tchkNum},
&Gfx::opSetFillGray, &Gfx::psSetFillGray},
{"h", 0, {tchkNone},
&Gfx::opClosePath, &Gfx::psClosePath},
{"i", 1, {tchkNum},
&Gfx::opSetFlat, &Gfx::psSetFlat},
{"j", 1, {tchkInt},
&Gfx::opSetLineJoin, &Gfx::psSetLineJoin},
{"k", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
&Gfx::opSetFillCMYKColor, &Gfx::psSetFillCMYKColor},
{"l", 2, {tchkNum, tchkNum},
&Gfx::opLineTo, &Gfx::psLineTo},
{"m", 2, {tchkNum, tchkNum},
&Gfx::opMoveTo, &Gfx::psMoveTo},
{"n", 0, {tchkNone},
&Gfx::opEndPath, &Gfx::psEndPath},
{"q", 0, {tchkNone},
&Gfx::opSave, &Gfx::psSave},
{"re", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
&Gfx::opRectangle, &Gfx::psRectangle},
{"rg", 3, {tchkNum, tchkNum, tchkNum},
&Gfx::opSetFillRGBColor, &Gfx::psSetFillRGBColor},
{"s", 0, {tchkNone},
&Gfx::opCloseStroke, &Gfx::psCloseStroke},
{"v", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
&Gfx::opCurveTo1, &Gfx::psCurveTo1},
{"w", 1, {tchkNum},
&Gfx::opSetLineWidth, &Gfx::psSetLineWidth},
{"y", 4, {tchkNum, tchkNum, tchkNum, tchkNum},
&Gfx::opCurveTo2, &Gfx::psCurveTo2}
};
#define numOps (sizeof(opTab) / sizeof(Operator))
#endif
#ifdef __riscos
// snb94r@ecs.soton.ac.uk added this - this is ugly, and add_Gfx_op should abort()
// if the size is exceeded./
#define numOps 58
Operator* Gfx::opTab = 0;
#include "GfxTable.h"
void Gfx::add_Gfx_op(const char *name, int argc,
void (Gfx::*f1)(Object []), void (Gfx::*f2)(Object []), ...)
{
static int addctr = 0;
va_list ap;
/* bitwise copy is OK */
strcpy(opTab[addctr].name, name);
opTab[addctr].numArgs = argc;
opTab[addctr].func = f1;
opTab[addctr].psFunc = f2;
if (!argc) argc = 1;
va_start(ap, f2);
// jump out to C because cfront rejects va_arg
enter_Gfx_ops((int *)(opTab[addctr].tchk), argc, ap);
va_end(ap);
if (++addctr >= numOps) {
--addctr;
}
}
void Gfx::init_opTab()
// new function by snb to initialise the table
{
static int done = 0;
if (done++) return;
opTab = new Operator[numOps];
/* autogenerated by: gawk -f awks.script cmdtable > sourcecode */
add_Gfx_op("\"",3,&Gfx::opMoveSetShowText,&Gfx::psMoveSetShowText,tchkNum,tchkNum,tchkString);
add_Gfx_op("'",1,&Gfx::opMoveShowText,&Gfx::psMoveShowText,tchkString);
add_Gfx_op("B",0,&Gfx::opFillStroke,&Gfx::psFillStroke,tchkNone);
add_Gfx_op("B*",0,&Gfx::opEOFillStroke,&Gfx::psEOFillStroke,tchkNone);
add_Gfx_op("BI",0,&Gfx::opBeginImage,&Gfx::psBeginImage,tchkNone);
add_Gfx_op("BT",0,&Gfx::opBeginText,&Gfx::psBeginText,tchkNone);
add_Gfx_op("Do",1,&Gfx::opXObject,&Gfx::psXObject,tchkName);
add_Gfx_op("EI",0,&Gfx::opEndImage,&Gfx::psEndImage,tchkNone);
add_Gfx_op("ET",0,&Gfx::opEndText,&Gfx::psEndText,tchkNone);
add_Gfx_op("F",0,&Gfx::opFill,&Gfx::psFill,tchkNone);
add_Gfx_op("G",1,&Gfx::opSetStrokeGray,&Gfx::psSetStrokeGray,tchkNum);
add_Gfx_op("ID",0,&Gfx::opImageData,&Gfx::psImageData,tchkNone);
add_Gfx_op("J",1,&Gfx::opSetLineCap,&Gfx::psSetLineCap,tchkInt);
add_Gfx_op("K",4,&Gfx::opSetStrokeCMYKColor,&Gfx::psSetStrokeCMYKColor,tchkNum,tchkNum,tchkNum,tchkNum);
add_Gfx_op("M",1,&Gfx::opSetMiterLimit,&Gfx::psSetMiterLimit,tchkNum);
add_Gfx_op("Q",0,&Gfx::opRestore,&Gfx::psRestore,tchkNone);
add_Gfx_op("RG",3,&Gfx::opSetStrokeRGBColor,&Gfx::psSetStrokeRGBColor,tchkNum,tchkNum,tchkNum);
add_Gfx_op("S",0,&Gfx::opStroke,&Gfx::psStroke,tchkNone);
add_Gfx_op("T*",0,&Gfx::opTextNextLine,&Gfx::psTextNextLine,tchkNone);
add_Gfx_op("TD",2,&Gfx::opTextMoveSet,&Gfx::psTextMoveSet,tchkNum,tchkNum);
add_Gfx_op("TJ",1,&Gfx::opShowSpaceText,&Gfx::psShowSpaceText,tchkArray);
add_Gfx_op("TL",1,&Gfx::opSetTextLeading,&Gfx::psSetTextLeading,tchkNum);
add_Gfx_op("Tc",1,&Gfx::opSetCharSpacing,&Gfx::psSetCharSpacing,tchkNum);
add_Gfx_op("Td",2,&Gfx::opTextMove,&Gfx::psTextMove,tchkNum,tchkNum);
add_Gfx_op("Tf",2,&Gfx::opSetFont,&Gfx::psSetFont,tchkName,tchkNum);
add_Gfx_op("Tj",1,&Gfx::opShowText,&Gfx::psShowText,tchkString);
add_Gfx_op("Tm",6,&Gfx::opSetTextMatrix,&Gfx::psSetTextMatrix,tchkNum,tchkNum,tchkNum,tchkNum,tchkNum,tchkNum);
add_Gfx_op("Tr",1,&Gfx::opSetTextRender,&Gfx::psSetTextRender,tchkInt);
add_Gfx_op("Ts",1,&Gfx::opSetTextRise,&Gfx::psSetTextRise,tchkNum);
add_Gfx_op("Tw",1,&Gfx::opSetWordSpacing,&Gfx::psSetWordSpacing,tchkNum);
add_Gfx_op("Tz",1,&Gfx::opSetHorizScaling,&Gfx::psSetHorizScaling,tchkNum);
add_Gfx_op("W",0,&Gfx::opClip,&Gfx::psClip,tchkNone);
add_Gfx_op("W*",0,&Gfx::opEOClip,&Gfx::psEOClip,tchkNone);
add_Gfx_op("b",0,&Gfx::opCloseFillStroke,&Gfx::psCloseFillStroke,tchkNone);
add_Gfx_op("b*",0,&Gfx::opCloseEOFillStroke,&Gfx::psCloseEOFillStroke,tchkNone);
add_Gfx_op("c",6,&Gfx::opCurveTo,&Gfx::psCurveTo,tchkNum,tchkNum,tchkNum,tchkNum,tchkNum,tchkNum);
add_Gfx_op("cm",6,&Gfx::opConcat,&Gfx::psConcat,tchkNum,tchkNum,tchkNum,tchkNum,tchkNum,tchkNum);
add_Gfx_op("d",2,&Gfx::opSetDash,&Gfx::psSetDash,tchkArray,tchkNum);
add_Gfx_op("d0",2,&Gfx::opSetCharWidth,&Gfx::psSetCharWidth,tchkNum,tchkNum);
add_Gfx_op("d1",2,&Gfx::opSetCacheDevice,&Gfx::psSetCacheDevice,tchkNum,tchkNum);
add_Gfx_op("f",0,&Gfx::opFill,&Gfx::psFill,tchkNone);
add_Gfx_op("f*",0,&Gfx::opEOFill,&Gfx::psEOFill,tchkNone);
add_Gfx_op("g",1,&Gfx::opSetFillGray,&Gfx::psSetFillGray,tchkNum);
add_Gfx_op("h",0,&Gfx::opClosePath,&Gfx::psClosePath,tchkNone);
add_Gfx_op("i",1,&Gfx::opSetFlat,&Gfx::psSetFlat,tchkNum);
add_Gfx_op("j",1,&Gfx::opSetLineJoin,&Gfx::psSetLineJoin,tchkInt);
add_Gfx_op("k",4,&Gfx::opSetFillCMYKColor,&Gfx::psSetFillCMYKColor,tchkNum,tchkNum,tchkNum,tchkNum);
add_Gfx_op("l",2,&Gfx::opLineTo,&Gfx::psLineTo,tchkNum,tchkNum);
add_Gfx_op("m",2,&Gfx::opMoveTo,&Gfx::psMoveTo,tchkNum,tchkNum);
add_Gfx_op("n",0,&Gfx::opEndPath,&Gfx::psEndPath,tchkNone);
add_Gfx_op("q",0,&Gfx::opSave,&Gfx::psSave,tchkNone);
add_Gfx_op("re",4,&Gfx::opRectangle,&Gfx::psRectangle,tchkNum,tchkNum,tchkNum,tchkNum);
add_Gfx_op("rg",3,&Gfx::opSetFillRGBColor,&Gfx::psSetFillRGBColor,tchkNum,tchkNum,tchkNum);
add_Gfx_op("s",0,&Gfx::opCloseStroke,&Gfx::psCloseStroke,tchkNone);
add_Gfx_op("v",4,&Gfx::opCurveTo1,&Gfx::psCurveTo1,tchkNum,tchkNum,tchkNum,tchkNum);
add_Gfx_op("w",1,&Gfx::opSetLineWidth,&Gfx::psSetLineWidth,tchkNum);
add_Gfx_op("y",4,&Gfx::opCurveTo2,&Gfx::psCurveTo2,tchkNum,tchkNum,tchkNum,tchkNum);
}
// end of insertion by snb94r@ecs.soton.ac.uk
#endif
//------------------------------------------------------------------------
// Gfx
//------------------------------------------------------------------------
Gfx::Gfx(OutputDev *out1, Dict *fontDict, Dict *xObjDict1,
int dpi, int x1, int y1, int x2, int y2, int rotate) {
#ifndef __riscos
// snb94r@ecs.soton.ac.uk added this to construct the operator table
init_opTab();
#endif
out = out1;
psOut = NULL;
if (fontDict)
fonts = new GfxFontDict(fontDict);
else
fonts = NULL;
xObjDict = xObjDict1;
state = new GfxState(dpi, x1, y1, x2, y2, rotate, out->upsideDown());
fontChanged = gFalse;
clip = clipNone;
psFont = NULL;
psFontSize = 1;
psGfxFont = NULL;
out->updateAll(state);
out->setPageSize(state->getPageWidth(), state->getPageHeight());
out->setCTM(state->getCTM());
out->clear();
}
Gfx::Gfx(PSOutput *psOut1, Dict *fontDict, Dict *xObjDict1,
int dpi, int x1, int y1, int x2, int y2, int rotate) {
#ifndef __riscos
// snb94r@ecs.soton.ac.uk added this to construct the operator table
init_opTab();
#endif
psOut = psOut1;
out = NULL;
//~ the fonts are needed to adjust for imperfect match with PS fonts
if (fontDict)
fonts = new GfxFontDict(fontDict);
else
fonts = NULL;
xObjDict = xObjDict1;
state = NULL;
fontChanged = gFalse;
clip = clipNone;
psFont = NULL;
psFontSize = 1;
psGfxFont = NULL;
}
Gfx::~Gfx() {
if (fonts)
delete fonts;
if (state)
delete state;
if (psFont)
delete psFont;
}
void Gfx::display(Array *a1) {
cover("Gfx::display(Array)");
parser = NULL;
a = a1;
index = 0;
go();
}
void Gfx::display(Stream *str1) {
cover("Gfx::display(Stream)");
parser = new Parser(new Lexer(str1, gFalse));
a = NULL;
go();
}
void Gfx::go() {
Object obj;
Object args[maxArgs];
int i, j;
i = 0;
nextObj(&obj);
while (!obj.isEOF()) {
if (obj.isCmd()) {
if (printCommands) {
obj.print(stdout);
for (j = 0; j < i; ++j) {
printf(" ");
args[j].print(stdout);
}
printf("\n");
}
execOp(&obj, args, i);
obj.free();
for (j = 0; j < i; ++j)
args[j].free();
i = 0;
} else if (i < maxArgs) {
args[i++] = obj;
} else {
error(0, "Too many args in content stream");
if (printCommands) {
printf("throwing away arg: ");
obj.print(stdout);
printf("\n");
}
obj.free();
}
nextObj(&obj);
}
obj.free();
if (i > 0) {
error(0, "Leftover args in content stream");
for (j = 0; j < i; ++j)
args[j].free();
}
done();
if (out)
out->dump();
if (printCommands)
fflush(stdout);
}
void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
Operator *op;
char *name;
int i;
// find operator
name = cmd->getName();
if (!(op = findOp(name))) {
error(0, "Unknown operator '%s'", name);
return;
}
// type check args
if (numArgs != op->numArgs) {
error(0, "Wrong number (%d) of args to '%s' operator", numArgs, name);
return;
}
for (i = 0; i < numArgs; ++i) {
if (!checkArg(&args[i], op->tchk[i])) {
error(0, "Arg #%d to '%s' operator is wrong type (%s)",
i, name, args[i].getTypeName());
return;
}
}
// do it
if (out)
(this->*op->func)(args);
else
(this->*op->psFunc)(args);
}
Operator *Gfx::findOp(char *name) {
int a, b, m, cmp;
a = -1;
b = numOps;
// invariant: opTab[a] < name < opTab[b]
while (b - a > 1) {
m = (a + b) / 2;
cmp = strcmp(opTab[m].name, name);
if (cmp < 0)
a = m;
else if (cmp > 0)
b = m;
else
a = b = m;
}
if (cmp != 0)
return NULL;
return &opTab[a];
}
GBool Gfx::checkArg(Object *arg, TchkType type) {
switch (type) {
case tchkBool: return arg->isBool();
case tchkInt: return arg->isInt();
case tchkNum: return arg->isNum();
case tchkString: return arg->isString();
case tchkName: return arg->isName();
case tchkArray: return arg->isArray();
case tchkNone: return gFalse;
}
return gFalse;
}
Object *Gfx::nextObj(Object *obj) {
if (a) {
if (index < a->getLength())
a->get(index++, obj);
else
obj->initEOF();
} else {
parser->getObj(obj);
}
return obj;
}
void Gfx::done() {
if (parser)
delete parser;
}
//------------------------------------------------------------------------
// graphics state operators
//------------------------------------------------------------------------
void Gfx::opSave(Object args[]) {
cover("Gfx::opSave");
out->saveState(state);
state = state->save();
}
void Gfx::psSave(Object args[]) {
psOut->writePS("q\n");
}
void Gfx::opRestore(Object args[]) {
cover("Gfx::opRestore");
state = state->restore();
out->restoreState(state);
}
void Gfx::psRestore(Object args[]) {
psOut->writePS("Q\n");
}
void Gfx::opConcat(Object args[]) {
cover("Gfx::opConcat");
state->concatCTM(args[0].getNum(), args[1].getNum(),
args[2].getNum(), args[3].getNum(),
args[4].getNum(), args[5].getNum());
out->updateCTM(state);
fontChanged = gTrue;
}
void Gfx::psConcat(Object args[]) {
psOut->writePS("[%g %g %g %g %g %g] cm\n",
args[0].getNum(), args[1].getNum(),
args[2].getNum(), args[3].getNum(),
args[4].getNum(), args[5].getNum());
}
void Gfx::opSetDash(Object args[]) {
Array *a;
int length;
Object obj;
double *dash;
int i;
cover("Gfx::opSetDash");
a = args[0].getArray();
length = a->getLength();
if (length == 0) {
dash = NULL;
} else {
dash = (double *)gmalloc(length * sizeof(double));
for (i = 0; i < length; ++i) {
dash[i] = a->get(i, &obj)->getNum();
obj.free();
}
}
state->setLineDash(dash, length, args[1].getNum());
out->updateLineDash(state);
}
void Gfx::psSetDash(Object args[]) {
Array *a;
int length;
Object obj;
int i;
a = args[0].getArray();
length = a->getLength();
psOut->writePS("[");
for (i = 0; i < length; ++i) {
psOut->writePS("%g%s", a->get(i, &obj)->getNum(),
(i == length-1) ? "" : " ");
obj.free();
}
psOut->writePS("] %g d\n", args[1].getNum());
}
void Gfx::opSetFlat(Object args[]) {
cover("Gfx::opSetFlat");
state->setFlatness((int)args[0].getNum());
out->updateFlatness(state);
}
void Gfx::psSetFlat(Object args[]) {
psOut->writePS("%g i\n", args[0].getNum());
}
void Gfx::opSetLineJoin(Object args[]) {
cover("Gfx::opSetLineJoin");
state->setLineJoin(args[0].getInt());
out->updateLineJoin(state);
}
void Gfx::psSetLineJoin(Object args[]) {
psOut->writePS("%d j\n", args[0].getInt());
}
void Gfx::opSetLineCap(Object args[]) {
cover("Gfx::opSetLineCap");
state->setLineCap(args[0].getInt());
out->updateLineCap(state);
}
void Gfx::psSetLineCap(Object args[]) {
psOut->writePS("%d J\n", args[0].getInt());
}
void Gfx::opSetMiterLimit(Object args[]) {
cover("Gfx::opSetMiterLimit");
state->setMiterLimit(args[0].getNum());
out->updateMiterLimit(state);
}
void Gfx::psSetMiterLimit(Object args[]) {
psOut->writePS("%g M\n", args[0].getNum());
}
void Gfx::opSetLineWidth(Object args[]) {
cover("Gfx::opSetLineWidth");
state->setLineWidth(args[0].getNum());
out->updateLineWidth(state);
}
void Gfx::psSetLineWidth(Object args[]) {
psOut->writePS("%g w\n", args[0].getNum());
}
//------------------------------------------------------------------------
// color operators
//------------------------------------------------------------------------
void Gfx::opSetFillGray(Object args[]) {
cover("Gfx::opSetFillGray");
state->setFillGray(args[0].getNum());
out->updateFillColor(state);
}
void Gfx::psSetFillGray(Object args[]) {
psOut->writePS("%g g\n", args[0].getNum());
}
void Gfx::opSetStrokeGray(Object args[]) {
cover("Gfx::opSetStrokeGray");
state->setStrokeGray(args[0].getNum());
out->updateStrokeColor(state);
}
void Gfx::psSetStrokeGray(Object args[]) {
psOut->writePS("%g G\n", args[0].getNum());
}
void Gfx::opSetFillCMYKColor(Object args[]) {
cover("Gfx::opSetFillCMYKColor");
state->setFillCMYK(args[0].getNum(), args[1].getNum(),
args[2].getNum(), args[3].getNum());
out->updateFillColor(state);
}
void Gfx::psSetFillCMYKColor(Object args[]) {
psOut->writePS("%g %g %g %g k\n",
args[0].getNum(), args[1].getNum(),
args[2].getNum(), args[3].getNum());
}
void Gfx::opSetStrokeCMYKColor(Object args[]) {
cover("Gfx::opSetStrokeCMYKColor");
state->setStrokeCMYK(args[0].getNum(), args[1].getNum(),
args[2].getNum(), args[3].getNum());
out->updateStrokeColor(state);
}
void Gfx::psSetStrokeCMYKColor(Object args[]) {
psOut->writePS("%g %g %g %g K\n",
args[0].getNum(), args[1].getNum(),
args[2].getNum(), args[3].getNum());
}
void Gfx::opSetFillRGBColor(Object args[]) {
cover("Gfx::opSetFillRGBColor");
state->setFillRGB(args[0].getNum(), args[1].getNum(), args[2].getNum());
out->updateFillColor(state);
}
void Gfx::psSetFillRGBColor(Object args[]) {
psOut->writePS("%g %g %g rg\n",
args[0].getNum(), args[1].getNum(), args[2].getNum());
}
void Gfx::opSetStrokeRGBColor(Object args[]) {
cover("Gfx::opSetStrokeRGBColor");
state->setStrokeRGB(args[0].getNum(), args[1].getNum(), args[2].getNum());
out->updateStrokeColor(state);
}
void Gfx::psSetStrokeRGBColor(Object args[]) {
psOut->writePS("%g %g %g RG\n",
args[0].getNum(), args[1].getNum(), args[2].getNum());
}
//------------------------------------------------------------------------
// path segment operators
//------------------------------------------------------------------------
void Gfx::opMoveTo(Object args[]) {
cover("Gfx::opMoveTo");
state->moveTo(args[0].getNum(), args[1].getNum());
}
void Gfx::psMoveTo(Object args[]) {
psOut->writePS("%g %g m\n", args[0].getNum(), args[1].getNum());
}
void Gfx::opLineTo(Object args[]) {
cover("Gfx::opLineTo");
if (!state->isPath()) {
error(0, "No current point in lineto");
return;
}
state->lineTo(args[0].getNum(), args[1].getNum());
}
void Gfx::psLineTo(Object args[]) {
psOut->writePS("%g %g l\n", args[0].getNum(), args[1].getNum());
}
void Gfx::opCurveTo(Object args[]) {
double x1, y1, x2, y2, x3, y3;
cover("Gfx::opCurveTo");
if (!state->isPath()) {
error(0, "No current point in curveto");
return;
}
x1 = args[0].getNum();
y1 = args[1].getNum();
x2 = args[2].getNum();
y2 = args[3].getNum();
x3 = args[4].getNum();
y3 = args[5].getNum();
state->curveTo(x1, y1, x2, y2, x3, y3);
}
void Gfx::psCurveTo(Object args[]) {
psOut->writePS("%g %g %g %g %g %g c\n",
args[0].getNum(), args[1].getNum(), args[2].getNum(),
args[3].getNum(), args[4].getNum(), args[5].getNum());
}
void Gfx::opCurveTo1(Object args[]) {
double x1, y1, x2, y2, x3, y3;
cover("Gfx::opCurveTo1");
if (!state->isPath()) {
error(0, "No current point in curveto1");
return;
}
x1 = state->getCurX();
y1 = state->getCurY();
x2 = args[0].getNum();
y2 = args[1].getNum();
x3 = args[2].getNum();
y3 = args[3].getNum();
state->curveTo(x1, y1, x2, y2, x3, y3);
}
void Gfx::psCurveTo1(Object args[]) {
psOut->writePS("%g %g %g %g v\n",
args[0].getNum(), args[1].getNum(),
args[2].getNum(), args[3].getNum());
}
void Gfx::opCurveTo2(Object args[]) {
double x1, y1, x2, y2, x3, y3;
cover("Gfx::opCurveTo2");
if (!state->isPath()) {
error(0, "No current point in curveto2");
return;
}
x1 = args[0].getNum();
y1 = args[1].getNum();
x2 = args[2].getNum();
y2 = args[3].getNum();
x3 = x2;
y3 = y2;
state->curveTo(x1, y1, x2, y2, x3, y3);
}
void Gfx::psCurveTo2(Object args[]) {
psOut->writePS("%g %g %g %g y\n",
args[0].getNum(), args[1].getNum(),
args[2].getNum(), args[3].getNum());
}
void Gfx::opRectangle(Object args[]) {
double x, y, w, h;
cover("Gfx::opRectangle");
x = args[0].getNum();
y = args[1].getNum();
w = args[2].getNum();
h = args[3].getNum();
state->moveTo(x, y);
state->lineTo(x + w, y);
state->lineTo(x + w, y + h);
state->lineTo(x, y + h);
state->closePath();
}
void Gfx::psRectangle(Object args[]) {
psOut->writePS("%g %g %g %g re\n",
args[0].getNum(), args[1].getNum(),
args[2].getNum(), args[3].getNum());
}
void Gfx::opClosePath(Object args[]) {
GfxPath *path;
cover("Gfx::opClosePath");
if (!state->isPath()) {
error(0, "No current point in closepath");
return;
}
state->closePath();
path = state->getPath();
}
void Gfx::psClosePath(Object args[]) {
psOut->writePS("h\n");
}
//------------------------------------------------------------------------
// path painting operators
//------------------------------------------------------------------------
void Gfx::opEndPath(Object args[]) {
cover("Gfx::opEndPath");
doEndPath();
}
void Gfx::psEndPath(Object args[]) {
if (clip != clipNone)
psDoClip(gFalse);
psOut->writePS("n\n");
}
void Gfx::opStroke(Object args[]) {
cover("Gfx::opStroke");
if (!state->isPath()) {
error(0, "No path in stroke");
return;
}
out->stroke(state);
doEndPath();
}
void Gfx::psStroke(Object args[]) {
if (clip != clipNone)
psOut->writePS("gsave\n");
psOut->writePS("S\n");
if (clip != clipNone)
psDoClip(gTrue);
}
void Gfx::opCloseStroke(Object args[]) {
cover("Gfx::opCloseStroke");
if (!state->isPath()) {
error(0, "No path in closepath/stroke");
return;
}
state->closePath();
out->stroke(state);
doEndPath();
}
void Gfx::psCloseStroke(Object args[]) {
if (clip != clipNone)
psOut->writePS("gsave\n");
psOut->writePS("s\n");
if (clip != clipNone)
psDoClip(gTrue);
}
void Gfx::opFill(Object args[]) {
cover("Gfx::opFill");
if (!state->isPath()) {
error(0, "No path in fill");
return;
}
out->fill(state);
doEndPath();
}
void Gfx::psFill(Object args[]) {
if (clip != clipNone)
psOut->writePS("gsave\n");
psOut->writePS("f\n");
if (clip != clipNone)
psDoClip(gTrue);
}
void Gfx::opEOFill(Object args[]) {
cover("Gfx::opEOFill");
if (!state->isPath()) {
error(0, "No path in eofill");
return;
}
out->eoFill(state);
doEndPath();
}
void Gfx::psEOFill(Object args[]) {
if (clip != clipNone)
psOut->writePS("gsave\n");
psOut->writePS("f*\n");
if (clip != clipNone)
psDoClip(gTrue);
}
void Gfx::opFillStroke(Object args[]) {
cover("Gfx::opFillStroke");
if (!state->isPath()) {
error(0, "No path in fill/stroke");
return;
}
out->fill(state);
out->stroke(state);
doEndPath();
}
void Gfx::psFillStroke(Object args[]) {
if (clip != clipNone)
psOut->writePS("gsave\n");
psOut->writePS("B\n");
if (clip != clipNone)
psDoClip(gTrue);
}
void Gfx::opCloseFillStroke(Object args[]) {
cover("Gfx::opCloseFillStroke");
if (!state->isPath()) {
error(0, "No path in closepath/fill/stroke");
return;
}
state->closePath();
out->fill(state);
out->stroke(state);
doEndPath();
}
void Gfx::psCloseFillStroke(Object args[]) {
if (clip != clipNone)
psOut->writePS("gsave\n");
psOut->writePS("b\n");
if (clip != clipNone)
psDoClip(gTrue);
}
void Gfx::opEOFillStroke(Object args[]) {
cover("Gfx::opEOFillStroke");
if (!state->isPath()) {
error(0, "No path in eofill/stroke");
return;
}
out->eoFill(state);
out->stroke(state);
doEndPath();
}
void Gfx::psEOFillStroke(Object args[]) {
if (clip != clipNone)
psOut->writePS("gsave\n");
psOut->writePS("B*\n");
if (clip != clipNone)
psDoClip(gTrue);
}
void Gfx::opCloseEOFillStroke(Object args[]) {
cover("Gfx::opCloseEOFillStroke");
if (!state->isPath()) {
error(0, "No path in closepath/eofill/stroke");
return;
}
state->closePath();
out->eoFill(state);
out->stroke(state);
doEndPath();
}
void Gfx::psCloseEOFillStroke(Object args[]) {
if (clip != clipNone)
psOut->writePS("gsave\n");
psOut->writePS("b*\n");
if (clip != clipNone)
psDoClip(gTrue);
}
void Gfx::doEndPath() {
if (clip == clipNormal)
out->clip(state);
else if (clip == clipEO)
out->eoClip(state);
clip = clipNone;
state->clearPath();
}
void Gfx::psDoClip(GBool needRestore) {
if (needRestore)
psOut->writePS("grestore\n");
if (clip == clipNormal)
psOut->writePS("clip\n");
else
psOut->writePS("eoclip\n");
if (needRestore)
psOut->writePS("newpath\n");
clip = clipNone;
}
//------------------------------------------------------------------------
// path clipping operators
//------------------------------------------------------------------------
void Gfx::opClip(Object args[]) {
cover("Gfx::opClip");
clip = clipNormal;
}
void Gfx::psClip(Object args[]) {
clip = clipNormal;
}
void Gfx::opEOClip(Object args[]) {
cover("Gfx::opEOClip");
clip = clipEO;
}
void Gfx::psEOClip(Object args[]) {
clip = clipEO;
}
//------------------------------------------------------------------------
// text object operators
//------------------------------------------------------------------------
void Gfx::opBeginText(Object args[]) {
cover("Gfx::opBeginText");
state->setTextMat(1, 0, 0, 1, 0, 0);
state->textMoveTo(0, 0);
fontChanged = gTrue;
}
void Gfx::psBeginText(Object args[]) {
psOut->writePS("[1 0 0 1 0 0] Tm\n");
fontChanged = gTrue;
}
void Gfx::opEndText(Object args[]) {
cover("Gfx::opEndText");
}
void Gfx::psEndText(Object args[]) {
}
//------------------------------------------------------------------------
// text state operators
//------------------------------------------------------------------------
void Gfx::opSetCharSpacing(Object args[]) {
cover("Gfx::opSetCharSpacing");
state->setCharSpace(args[0].getNum());
}
void Gfx::psSetCharSpacing(Object args[]) {
psOut->writePS("%g Tc\n", args[0].getNum());
}
void Gfx::opSetFont(Object args[]) {
GfxFont *font;
cover("Gfx::opSetFont");
if (!fonts) {
error(0, "setfont without font dictionary");
return;
}
if (!(font = fonts->lookup(args[0].getName()))) {
error(0, "unknown font tag '%s'", args[0].getName());
return;
}
if (printCommands) {
printf(" font: '%s' %g\n",
font->getName() ? font->getName()->getCString() : "???",
args[1].getNum());
}
state->setFont(font, args[1].getNum());
fontChanged = gTrue;
}
void Gfx::psSetFont(Object args[]) {
if (fonts)
psGfxFont = fonts->lookup(args[0].getName());
if (psFont)
delete psFont;
psFont = new GString(args[0].getName());
psFontSize = args[1].getNum();
fontChanged = gTrue;
}
void Gfx::opSetTextLeading(Object args[]) {
cover("Gfx::opSetTextLeading");
state->setLeading(args[0].getNum());
}
void Gfx::psSetTextLeading(Object args[]) {
psOut->writePS("%g TL\n", args[0].getNum());
}
void Gfx::opSetTextRender(Object args[]) {
cover("Gfx::opSetTextRender");
state->setRender(args[0].getInt());
}
void Gfx::psSetTextRender(Object args[]) {
int r;
r = args[0].getInt();
psOut->writePS("%d Tr\n", r);
}
void Gfx::opSetTextRise(Object args[]) {
cover("Gfx::opSetTextRise");
state->setRise(args[0].getNum());
}
void Gfx::psSetTextRise(Object args[]) {
psOut->writePS("%g Ts\n", args[0].getNum());
}
void Gfx::opSetWordSpacing(Object args[]) {
cover("Gfx::opSetWordSpacing");
state->setWordSpace(args[0].getNum());
}
void Gfx::psSetWordSpacing(Object args[]) {
psOut->writePS("%g Tw\n", args[0].getNum());
}
void Gfx::opSetHorizScaling(Object args[]) {
cover("Gfx::opSetHorizScaling");
state->setHorizScaling(args[0].getNum());
}
void Gfx::psSetHorizScaling(Object args[]) {
psOut->writePS("%g Tz\n", args[0].getNum());
}
//------------------------------------------------------------------------
// text positioning operators
//------------------------------------------------------------------------
void Gfx::opTextMove(Object args[]) {
double tx, ty;
cover("Gfx::opTextMove");
tx = state->getLineX() + args[0].getNum();
ty = state->getLineY() + args[1].getNum();
state->textMoveTo(tx, ty);
}
void Gfx::psTextMove(Object args[]) {
psOut->writePS("%g %g Td\n", args[0].getNum(), args[1].getNum());
}
void Gfx::opTextMoveSet(Object args[]) {
double tx, ty;
cover("Gfx::opTextMoveSet");
tx = state->getLineX() + args[0].getNum();
ty = args[1].getNum();
state->setLeading(-ty);
ty += state->getLineY();
state->textMoveTo(tx, ty);
}
void Gfx::psTextMoveSet(Object args[]) {
psOut->writePS("%g %g TD\n", args[0].getNum(), args[1].getNum());
}
void Gfx::opSetTextMatrix(Object args[]) {
cover("Gfx::opSetTextMatrix");
state->setTextMat(args[0].getNum(), args[1].getNum(),
args[2].getNum(), args[3].getNum(),
args[4].getNum(), args[5].getNum());
state->textMoveTo(0, 0);
fontChanged = gTrue;
}
void Gfx::psSetTextMatrix(Object args[]) {
psOut->writePS("[%g %g %g %g %g %g] Tm\n",
args[0].getNum(), args[1].getNum(),
args[2].getNum(), args[3].getNum(),
args[4].getNum(), args[5].getNum());
fontChanged = gTrue;
}
void Gfx::opTextNextLine(Object args[]) {
double tx, ty;
cover("Gfx::opTextNextLine");
tx = state->getLineX();
ty = state->getLineY() - state->getLeading();
state->textMoveTo(tx, ty);
}
void Gfx::psTextNextLine(Object args[]) {
psOut->writePS("T*\n");
}
//------------------------------------------------------------------------
// text string operators
//------------------------------------------------------------------------
void Gfx::opShowText(Object args[]) {
cover("Gfx::opShowText");
if (!state->getFont()) {
error(0, "No font in show");
return;
}
doShowText(args[0].getString());
}
void Gfx::psShowText(Object args[]) {
if (fontChanged) {
psOut->writePS("/%s %g Tf\n", psFont->getCString(), psFontSize);
fontChanged = gFalse;
}
psOut->writePSString(args[0].getString());
psOut->writePS(" %g Tj\n", psGfxFont->getWidth(args[0].getString()));
}
void Gfx::opMoveShowText(Object args[]) {
double tx, ty;
cover("Gfx::opMoveShowText");
if (!state->getFont()) {
error(0, "No font in move/show");
return;
}
tx = state->getLineX();
ty = state->getLineY() - state->getLeading();
state->textMoveTo(tx, ty);
doShowText(args[0].getString());
}
void Gfx::psMoveShowText(Object args[]) {
if (fontChanged) {
psOut->writePS("/%s %g Tf\n", psFont->getCString(), psFontSize);
fontChanged = gFalse;
}
psOut->writePS("T* ");
psOut->writePSString(args[0].getString());
psOut->writePS(" %g Tj\n", psGfxFont->getWidth(args[0].getString()));
}
void Gfx::opMoveSetShowText(Object args[]) {
double tx, ty;
cover("Gfx::opMoveSetShowText");
if (!state->getFont()) {
error(0, "No font in move/set/show");
return;
}
state->setWordSpace(args[0].getNum());
state->setCharSpace(args[1].getNum());
tx = state->getLineX();
ty = state->getLineY() - state->getLeading();
state->textMoveTo(tx, ty);
doShowText(args[2].getString());
}
void Gfx::psMoveSetShowText(Object args[]) {
if (fontChanged) {
psOut->writePS("/%s %g Tf\n", psFont->getCString(), psFontSize);
fontChanged = gFalse;
}
psOut->writePS("%g Tw %g Tc T* ", args[0].getNum(), args[1].getNum());
psOut->writePSString(args[2].getString());
psOut->writePS(" %g Tj\n", psGfxFont->getWidth(args[2].getString()));
}
void Gfx::opShowSpaceText(Object args[]) {
Array *a;
Object obj;
int i;
cover("Gfx::opShowSpaceText");
if (!state->getFont()) {
error(0, "No font in show/space");
return;
}
a = args[0].getArray();
for (i = 0; i < a->getLength(); ++i) {
a->get(i, &obj);
if (obj.isNum())
state->textShift(-obj.getNum() * 0.001 * state->getFontSize());
else if (obj.isString())
doShowText(obj.getString());
else
error(0, "Element of show/space array must be number or string");
obj.free();
}
}
void Gfx::psShowSpaceText(Object args[]) {
Array *a;
Object obj;
int i;
if (fontChanged) {
psOut->writePS("/%s %g Tf\n", psFont->getCString(), psFontSize);
fontChanged = gFalse;
}
a = args[0].getArray();
for (i = 0; i < a->getLength(); ++i) {
a->get(i, &obj);
if (obj.isNum()) {
psOut->writePS("%g TJm\n", obj.getNum());
} else if (obj.isString()) {
psOut->writePSString(obj.getString());
psOut->writePS(" %g Tj\n", psGfxFont->getWidth(obj.getString()));
}
obj.free();
}
}
void Gfx::doShowText(GString *s) {
Guchar *p;
int n;
double dx, dy;
if (fontChanged) {
out->updateFont(state);
fontChanged = gFalse;
}
state->textTransformDelta(0, state->getRise(), &dx, &dy);
for (p = (Guchar *)s->getCString(), n = s->getLength(); n; ++p, --n) {
if (*p != '\r' && *p != '\n') {
out->drawChar(state, state->getCurX() + dx, state->getCurY() + dy, *p);
if (*p == ' ')
state->textShift(state->getWordSpace());
}
state->textShift(state->getFontSize() * state->getFont()->getWidth(*p) +
state->getCharSpace());
}
}
//------------------------------------------------------------------------
// XObject operators
//------------------------------------------------------------------------
void Gfx::opXObject(Object args[]) {
Object obj1, obj2;
cover("Gfx::opXObject");
if (!xObjDict) {
error(0, "No XObject dictionary in 'Do' operator");
return;
}
xObjDict->lookup(args[0].getName(), &obj1);
if (!obj1.isStream("XObject")) {
error(0, "XObject '%s' is unknown or wrong type", args[0].getName());
obj1.free();
return;
}
obj1.streamGetDict()->lookup("Subtype", &obj2);
if (obj2.isName("Image"))
doImage(obj1.getStream());
else if (obj2.isName("Form"))
doForm(obj1.getStream());
else if (obj2.isName())
error(0, "Unknown XObject subtype '%s'", obj2.getName());
else
error(0, "XObject subtype is missing or wrong type");
obj2.free();
obj1.free();
}
void Gfx::psXObject(Object args[]) {
Object obj1, obj2;
if (!xObjDict) {
error(0, "No XObject dictionary in 'Do' operator");
return;
}
xObjDict->lookup(args[0].getName(), &obj1);
if (!obj1.isStream("XObject")) {
error(0, "XObject '%s' is unknown or wrong type", args[0].getName());
obj1.free();
return;
}
obj1.streamGetDict()->lookup("Subtype", &obj2);
if (obj2.isName("Image"))
psDoImage(obj1.getStream());
else if (obj2.isName("Form"))
psDoForm(obj1.getStream());
else if (obj2.isName())
error(0, "Unknown XObject subtype '%s'", obj2.getName());
else
error(0, "XObject subtype is missing or wrong type");
obj2.free();
obj1.free();
}
void Gfx::doImage(Stream *str) {
Dict *dict;
Object obj1, obj2;
int width, height;
int bits;
GBool mask;
GfxColorSpace *colorSpace;
GBool invert;
cover("Gfx::doImage");
// get stream dict
dict = str->getDict();
// get size
dict->lookup("Width", &obj1);
if (obj1.isNull()) {
obj1.free();
dict->lookup("W", &obj1);
}
if (!obj1.isInt())
goto err2;
width = obj1.getInt();
obj1.free();
dict->lookup("Height", &obj1);
if (obj1.isNull()) {
obj1.free();
dict->lookup("H", &obj1);
}
if (!obj1.isInt())
goto err2;
height = obj1.getInt();
obj1.free();
// image or mask?
dict->lookup("ImageMask", &obj1);
if (obj1.isNull()) {
obj1.free();
dict->lookup("IM", &obj1);
}
mask = gFalse;
if (obj1.isBool())
mask = obj1.getBool();
else if (!obj1.isNull())
goto err2;
obj1.free();
// bit depth
dict->lookup("BitsPerComponent", &obj1);
if (obj1.isNull()) {
obj1.free();
dict->lookup("BPC", &obj1);
}
if (!obj1.isInt())
goto err2;
bits = obj1.getInt();
obj1.free();
// display a mask
if (mask) {
if (bits != 1)
goto err1;
invert = gFalse;
dict->lookup("Decode", &obj1);
if (obj1.isNull()) {
obj1.free();
dict->lookup("D", &obj1);
}
if (obj1.isArray()) {
obj1.arrayGet(0, &obj2);
if (obj2.isInt() && obj2.getInt() == 1)
invert = gTrue;
obj2.free();
} else if (!obj1.isNull()) {
goto err2;
}
obj1.free();
out->drawImageMask(state, str, width, height, invert);
} else {
// get color space
dict->lookup("ColorSpace", &obj1);
if (obj1.isNull()) {
obj1.free();
dict->lookup("CS", &obj1);
}
if (!(obj1.isName() || obj1.isArray() || obj1.isNull()))
goto err2;
dict->lookup("Decode", &obj2);
if (obj1.isNull()) {
obj1.free();
dict->lookup("D", &obj1);
}
if (!(obj2.isArray() || obj2.isNull()))
goto err3;
colorSpace = new GfxColorSpace(bits, &obj1, &obj2);
if (!colorSpace->isOk())
goto err4;
obj1.free();
obj2.free();
// display an image
out->drawImage(state, str, width, height, colorSpace);
delete colorSpace;
}
return;
err4:
delete colorSpace;
err3:
obj2.free();
err2:
obj1.free();
err1:
error(0, "Bad image parameters");
}
void Gfx::psDoImage(Stream *str) {
psOut->writeImage(str->getDict(), str, gFalse);
}
void Gfx::doForm(Stream *str) {
cover("Gfx::doForm");
error(0, "Unimplemented: form");
}
void Gfx::psDoForm(Stream *str) {
error(0, "Unimplemented: form");
}
//------------------------------------------------------------------------
// in-line image operators
//------------------------------------------------------------------------
void Gfx::opBeginImage(Object args[]) {
Object obj;
Stream *str;
cover("Gfx::opBeginImage");
// build dict/stream
str = buildImageStream();
// display the image
if (str) {
doImage(str);
delete str;
}
// get 'EI' tag
nextObj(&obj);
if (!obj.isCmd("EI"))
error(0, "Expected 'EI' operator");
obj.free();
}
void Gfx::psBeginImage(Object args[]) {
Stream *str;
// build dict/stream
str = buildImageStream();
// display the image
// (writeImage() eats the 'EI' tag)
if (str) {
psOut->writeImage(str->getDict(), str, gTrue);
delete str;
}
}
Stream *Gfx::buildImageStream() {
Object dict;
Object obj;
char *key;
Stream *str;
// inline image must be in stream
if (!parser) {
error(0, "Inline image in array content stream");
return NULL;
}
// build dictionary
dict.initDict();
nextObj(&obj);
while (!obj.isCmd("ID") && !obj.isEOF()) {
if (!obj.isName()) {
error(0, "Dictionary key must be a name object");
obj.free();
nextObj(&obj);
} else {
key = copyString(obj.getName());
obj.free();
nextObj(&obj);
if (obj.isEOF() || obj.isError())
break;
dict.dictAdd(key, &obj);
}
nextObj(&obj);
}
if (obj.isEOF())
error(0, "End of file in inline image");
obj.free();
// make stream
str = new SubStream(parser->getStream(), &dict);
str = str->addFilters(&dict);
return str;
}
void Gfx::opImageData(Object args[]) {
error(0, "Internal: got 'ID' operator");
}
void Gfx::psImageData(Object args[]) {
error(0, "Internal: got 'ID' operator");
}
void Gfx::opEndImage(Object args[]) {
error(0, "Internal: got 'EI'operator");
}
void Gfx::psEndImage(Object args[]) {
error(0, "Internal: got 'EI'operator");
}
//------------------------------------------------------------------------
// type 3 font operators
//------------------------------------------------------------------------
void Gfx::opSetCharWidth(Object args[]) {
cover("Gfx::opSetCharWidth");
error(0, "Encountered 'd0' operator in content stream");
}
void Gfx::psSetCharWidth(Object args[]) {
}
void Gfx::opSetCacheDevice(Object args[]) {
cover("Gfx::opSetCacheDevice");
error(0, "Encountered 'd1' operator in content stream");
}
void Gfx::psSetCacheDevice(Object args[]) {
}